// EAXPresetsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "EAXPresetsDlg.h"
#include "EAXPresetMgr.h"
#include "StringDlg.h"
#include "Controls\PropertyItem.h"
#include "SoundBrowserDialog.h"
#include "SoundEventParameterDialog.h"

#define WM_UPDATEPROPERTIES	WM_APP+1

IMPLEMENT_DYNAMIC(CEAXPresetsDlg, CBaseLibraryDialog)

BEGIN_MESSAGE_MAP(CEAXPresetsDlg, CBaseLibraryDialog)
	ON_LBN_SELCHANGE(IDC_PRESETS, OnLbnSelchangePresets)
	ON_COMMAND(ID_SAVE, OnSavePreset)
	ON_COMMAND(ID_ADDPRESET, OnAddPreset)
	ON_COMMAND(ID_DELPRESET, OnDelPreset)
	ON_COMMAND(ID_PREVIEWPRESET, OnPreviewPreset)
	ON_COMMAND(ID_REVERB_PRESETS_IMPORT, OnImportPresets)
	ON_COMMAND(ID_REVERB_PRESETS_EXPORT, OnExportPresets)
	ON_COMMAND(ID_DB_REVERB_SELECTSOUND, OnOpenSoundBrowser)
	ON_WM_SIZE()
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	ON_MESSAGE(WM_UPDATEPROPERTIES, OnUpdateProperties)
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////////
CEAXPresetsDlg::CEAXPresetsDlg(CWnd* pParent /*=NULL*/)
: CBaseLibraryDialog(CEAXPresetsDlg::IDD, pParent),
m_nWidthPresets(0),
m_pEAXPresetMgr(NULL),
m_pSoundEventParameterDialog(NULL),
m_nSelectionIndex(-1)
{
		// Immediately create dialog.
		Create( CEAXPresetsDlg::IDD,pParent );
}

//////////////////////////////////////////////////////////////////////////
CEAXPresetsDlg::~CEAXPresetsDlg()
{
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::DoDataExchange(CDataExchange* pDX)
{
		CDialog::DoDataExchange(pDX);
		DDX_Control(pDX, IDC_PRESETS, m_wndPresets);
		DDX_Control(pDX, IDC_PARAMS, m_wndParams);
}

//////////////////////////////////////////////////////////////////////////
BOOL CEAXPresetsDlg::OnInitDialog()
{
		m_pEAXPresetMgr=GetIEditor()->GetEAXPresetMgr();
		m_pEAXPresetMgr->Load();
		UpdateData(false);
		CBaseLibraryDialog::OnInitDialog();
		CRect rc;
		InitToolbar(IDR_EAXPRESETS);
		// Resize the toolbar
		GetClientRect(rc);
		m_toolbar.SetWindowPos(NULL, 0, 0, rc.right, 70, SWP_NOZORDER);
		// TODO: Remove this if you don't want tool tips or a resizeable toolbar
		m_toolbar.SetBarStyle(m_toolbar.GetBarStyle()|CBRS_TOOLTIPS|CBRS_FLYBY);
		RecalcLayout();
		m_wndParams.SetUpdateCallback(functor(*this, &CEAXPresetsDlg::OnParamsChanged));
		Update();

		CRect rc2;
		m_wndPresets.GetClientRect( rc2 );
		m_nWidthPresets = rc2.right-rc2.left;

		if (!m_pSoundEventParameterDialog)
		{
				m_pSoundEventParameterDialog = new CSoundEventParameterDialog();
				if (m_pSoundEventParameterDialog)
				{
						m_pSoundEventParameterDialog->Create(IDD_SOUND_EVENTPARAMETER, this);
						m_pSoundEventParameterDialog->ShowWindow(SW_SHOWNOACTIVATE);

						if (m_pEAXPresetMgr)
						{
								m_pSoundEventParameterDialog->SetParamType(spREVERBWET);
								m_pSoundEventParameterDialog->SetName(m_pEAXPresetMgr->GetPreviewSoundName());
								m_pSoundEventParameterDialog->SetRange(-60.0f, 0.0f);
								m_pSoundEventParameterDialog->SetCurrentValue(m_pEAXPresetMgr->GetPreviewSoundWetVal());

								// We want the slider to be only half the width of its dialog
								m_pSoundEventParameterDialog->SetSliderWidthMultiplier(0.5f);
						}
				}
		}

		return TRUE;  // return TRUE unless you set the focus to a control
		// EXCEPTION: OCX Property Pages should return FALSE
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::InitToolbar( UINT nToolbarResID )
{
		// Create the toolbar
		m_toolbar.CreateEx(this, TBSTYLE_FLAT|TBSTYLE_WRAPABLE,	WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC);
		m_toolbar.LoadToolBarDepth(IDR_EAXPRESETS,32,ILC_COLOR32);
		m_toolbar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
		m_toolbar.CalcFixedLayout(0, TRUE);
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::Update()
{
		XmlNodeRef pRootNode=m_pEAXPresetMgr->GetRootNode();
		if (!pRootNode)
				return;
		int nCurSel=m_wndPresets.GetCurSel();
		m_wndPresets.ResetContent();
		CString sName;
		for (int i=0;i<pRootNode->getChildCount();i++)
		{
				XmlNodeRef pPresetNode=pRootNode->getChild(i);
				m_wndPresets.AddString(pPresetNode->getTag());
		}
		m_wndPresets.SetCurSel(nCurSel);
		OnLbnSelchangePresets();
}

//////////////////////////////////////////////////////////////////////////
LRESULT CEAXPresetsDlg::OnUpdateProperties(WPARAM wParam, LPARAM lParam)
{
		int nCurSel=m_wndPresets.GetCurSel();
		if (nCurSel<0)
				return -1;
		CString sCurSel;
		m_wndPresets.GetText(nCurSel, sCurSel);
		m_wndParams.EnableUpdateCallback(false);
		m_wndParams.CreateItems(m_pEAXPresetMgr->GetRootNode()->findChild(sCurSel.GetBuffer()));
		
		// The code below makes sure we expand the "EchoDSP" node.
		CPropertyItem* pRootItem  = m_wndParams.GetRootItem();
		CPropertyItem* pChildItem = NULL;
		CString sChildName;

		if (pRootItem)
		{
				int const nChildrenCount = pRootItem->GetChildCount();

				for (int nChildID = 0; nChildID < nChildrenCount; ++nChildID)
				{
						pChildItem = pRootItem->GetChild(nChildID);

						if (pChildItem)
						{
								sChildName = pChildItem->GetName();

								if (sChildName.CompareNoCase("EchoDSP") == 0)
								{
										m_wndParams.Expand(pChildItem, true);

										break;
								}
						}
				}
		}

		m_wndParams.EnableUpdateCallback(true);
		// Register the currently selected reverb preset.
		m_pEAXPresetMgr->RegisterPreset(sCurSel.GetString());

		return 0;
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnParamsChanged(XmlNodeRef pNode)
{
		if (!m_pEAXPresetMgr->UpdateParameter(pNode))
				AfxMessageBox("An error occured while updating script-tables.", MB_ICONEXCLAMATION | MB_OK);
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnLbnSelchangePresets()
{
		if (m_nSelectionIndex >= 0)
		{
				CString sText;
				m_wndPresets.GetText(m_nSelectionIndex, sText);

				m_pEAXPresetMgr->UnregisterPreset(sText.GetString());
		}

		m_nSelectionIndex = m_wndPresets.GetCurSel();

		if (m_nSelectionIndex < 0)
		{
				m_toolbar.GetToolBarCtrl().EnableButton(ID_DELPRESET, FALSE);
				XmlNodeRef pEmptyRoot=XmlHelpers::CreateXmlNode("Root");
				m_wndParams.CreateItems(pEmptyRoot);
				return;
		}
		else
		{
				m_toolbar.GetToolBarCtrl().EnableButton(ID_DELPRESET, TRUE);
		}

		PostMessage(WM_UPDATEPROPERTIES, 0, 0);
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnSavePreset()
{
		if (!m_pEAXPresetMgr->Save())
				AfxMessageBox("An error occured while saving Reverb-presets. Read-only ?", MB_ICONEXCLAMATION | MB_OK);
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnAddPreset()
{
		CStringDlg dlgName("Please enter name for preset:");
		if (dlgName.DoModal()==IDOK)
		{
				if (!m_pEAXPresetMgr->AddPreset(dlgName.GetString()))
						AfxMessageBox("Cannot add preset. Check if a preset with that name exist already and if the name is valid (A-Z, 0-9 (not first character)).", MB_ICONEXCLAMATION | MB_OK);
				else
				{
						m_pEAXPresetMgr->Reload();
						Update();
				}
		}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnDelPreset()
{
		int nCurSel=m_wndPresets.GetCurSel();
		if (nCurSel<0)
				return;
		if (AfxMessageBox("Are you sure you want to delete the Reverb-preset ?", MB_ICONQUESTION | MB_YESNO)==IDNO)
				return;
		CString sCurSel;
		m_wndPresets.GetText(nCurSel, sCurSel);
		if (!m_pEAXPresetMgr->DelPreset(sCurSel))
				AfxMessageBox("Cannot delete preset.", MB_ICONEXCLAMATION | MB_OK);
		else
				Update();
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnPreviewPreset()
{
		// Get the slider's current value.
		if (m_pSoundEventParameterDialog)
		{
				m_pEAXPresetMgr->SetPreviewSoundWetVal(m_pSoundEventParameterDialog->GetCurrentValue());
		}

		if (!m_pEAXPresetMgr->PreviewPreset())
		{
				AfxMessageBox("Cannot preview preset. File not found or SoundSystem disabled?", MB_ICONEXCLAMATION | MB_OK);
		}
		else
		{
				// The EAXPresetManager created a sound object, now assign its ID to the slider so it can manipulate it.
				m_pSoundEventParameterDialog->SetSoundID(m_pEAXPresetMgr->GetPreviewSoundID());
		}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnClose()
{
		CBaseLibraryDialog::OnClose();
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnDestroy()
{
		// In case there is a preset still playing make sure it stops immediately when the user closes the dialog
		SetActive(false);

		CBaseLibraryDialog::OnDestroy();
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnSize(UINT nType, int cx, int cy)
{
		if (m_wndPresets.m_hWnd)
		{
				CRect oWindowRect;
				GetClientRect( oWindowRect );

				const int kToolbarHeight = 40;
				const int kLeftMargin = 3;

				m_toolbar.SetWindowPos( NULL, 0, 0, oWindowRect.right, kToolbarHeight, SWP_NOZORDER );
				m_wndPresets.SetWindowPos( NULL, kLeftMargin, kToolbarHeight + 20, m_nWidthPresets, oWindowRect.bottom - oWindowRect.top - kToolbarHeight - 13, SWP_NOZORDER );

				CWnd* const pPresetsWnd = GetDlgItem( IDC_STATIC_PRESETS );

				if( pPresetsWnd )
				{
						pPresetsWnd->SetWindowPos( 0, kLeftMargin, kToolbarHeight + 3, 0, 0, SWP_NOSIZE );
				}

				// Set the slider dialog and the params list box control right beneath it
				if (m_pSoundEventParameterDialog)
				{
						m_pSoundEventParameterDialog->SetWindowPos( NULL, 13 + m_nWidthPresets, 60, oWindowRect.right - oWindowRect.left - 16 - m_nWidthPresets, 100, 0 );

						WINDOWPLACEMENT oPlacement = {0};
						m_pSoundEventParameterDialog->GetWindowPlacement( &oPlacement );

						// Set params header position
						CWnd* const pParamsHeader = GetDlgItem( IDC_PARAMS_TEXT );
						if (pParamsHeader)
								pParamsHeader->SetWindowPos( NULL, 13 + m_nWidthPresets, oPlacement.rcNormalPosition.bottom + 20, oWindowRect.right - oWindowRect.left - 16 - m_nWidthPresets, 15, SWP_NOZORDER );

						m_wndParams.SetWindowPos( NULL, 13 + m_nWidthPresets, oPlacement.rcNormalPosition.bottom + 45, oWindowRect.right - oWindowRect.left - 16 - m_nWidthPresets, oWindowRect.bottom - oWindowRect.top - 60, SWP_NOZORDER );
				}
				else
						m_wndParams.SetWindowPos( NULL, 13 + m_nWidthPresets, 50, oWindowRect.right - oWindowRect.left - 16 - m_nWidthPresets, oWindowRect.bottom - oWindowRect.top - 60, SWP_NOZORDER );
		}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnOpenSoundBrowser()
{
		CSoundBrowserDialog oDialog;
		CString oText;
		char const* pcText = NULL;

		if(m_pSoundEventParameterDialog)
				pcText = m_pSoundEventParameterDialog->GetName();

		oDialog.Init(pcText);
		if (oDialog.DoModal() == IDOK)
		{
				if(!oDialog.IsBrowse())
				{
						stack_string oSelection = oDialog.GetString();
						if(!oSelection.empty())
						{
								m_pEAXPresetMgr->SetPreviewSound(oSelection);
								float const fValue = m_pEAXPresetMgr->GetPreviewSoundWetVal();

								if (m_pSoundEventParameterDialog)
								{
										m_pSoundEventParameterDialog->SetName(oSelection);
										m_pSoundEventParameterDialog->SetCurrentValue(fValue);
										m_pEAXPresetMgr->SetReverbWetValueDefault(fValue);
								}
						}
				}
		}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::SetActive(bool bActive)
{
		int const nCurSel = m_wndPresets.GetCurSel();

		if (nCurSel >= 0)
		{
				CString sCurSel;
				m_wndPresets.GetText(nCurSel, sCurSel);

				if (!bActive)
				{
						m_pEAXPresetMgr->StopPreviewSound();
						m_pEAXPresetMgr->UnregisterPreset(sCurSel.GetString());
				}
				else
				{
						m_pEAXPresetMgr->RegisterPreset(sCurSel.GetString());
				}
		}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnImportPresets()
{
	if (m_pEAXPresetMgr)
	{
		m_pEAXPresetMgr->ImportPresets();
		Update();
	}
}

//////////////////////////////////////////////////////////////////////////
void CEAXPresetsDlg::OnExportPresets()
{
	if (m_pEAXPresetMgr)
	{
		m_pEAXPresetMgr->ExportPresets();
		Update();
	}
}
